const htmlOutModel = require('../model/sky-stat/htmlOut.js')
const request = require('request-promise-native')
const chem = require('chem-eb')
const Pack = require('../config')
const Mock = require('mockjs')
const phoneFind = require('../model/mobile_find')
const ipFind = require('../model/qqwry')()
const QrCode = require('qrcode-reader')
const jimp = require('jimp')
const genAvatar = require('jdenticon')
const crypto = require('crypto')
let qr = new QrCode()
const geo = require('../model/geohash.js')
const { copyFileSync } = require('fs')
module.exports = {
  async today (ctx) {
    const data = ctx.checkedData.data
    const nowDate = $.now()
    const month = nowDate.getMonth() + 1
    const day = nowDate.getDate()
    const r = await sqliteDB.all(
      `select desc,year,type from today  where month=${month} and day=${day} order by year`
    )

    if (!data.isJson) {
      ctx.type = 'text/html'
      const tdTitle = ['序号', '世纪', '年代', '描述', '类型']
      const objHtml = r
      const title = nowDate.date2Str().split(' ')[0] + ' 历史上的今天'
      ctx.body = htmlOutModel.outHtml(title, [
        {
          title: title,
          dataTitleArr: tdTitle,
          dataArr: processData(objHtml)
        }
      ])
      //console.log(processData(objHtml))
    } else {
      ctx.throwCode(200, 'skyApi', r)
    }
  },
  async genImg (ctx) {
    const { size } = ctx.checkedData.data
    const rndColor = $.color.random()
    const rndRgb = rndColor.toRgb()
    const comColor = $.color({
      r: 255 - rndRgb.r,
      g: 255 - rndRgb.g,
      b: 255 - rndRgb.b,
      a: 1
    })
    const r = $.Mock.genImg({
      size,
      bg: '#' + rndColor.toHex(),
      text: '我是占位符',
      fc: '#' + comColor.toHex()
    })
    if (r === -1) {
      ctx.throwCode('404', '格式有误')
    } else {
      ctx.type = 'image/svg+xml'
      ctx.body = r
    }
  },
  async qrcode (ctx) {
    const { str } = ctx.checkedData.data
    ctx.type = 'html'
    console.log($.qrcode)
    ctx.body = $.qrcode.generateHTML(
      str + '' ||
        'https://github.com/kongnet/skybase/blob/master/BestPractice.md'
    )
  },
  async getBing (ctx) {
    let r = await req(
      'https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1',
      'GET',
      true
    )
    //console.log(r)
    ctx.type = 'html'
    ctx.body = `<img src='https://cn.bing.com${r.images[0].url}'></>`
  },
  async chem (ctx) {
    const { eqInput } = ctx.checkedData.data
    console.log(eqInput)
    const r = chem(eqInput)
    ctx.ok({ eqInput: r.oriChem, eqOutput: r.outChem }, '成功')
  },
  async chartImg (ctx) {
    const { chartJsonStr } = ctx.checkedData.data
    //console.log('chart:', chartJsonStr)
    await webPage.goto(Pack.puppeteer.chartUrl + 'chart.html')
    await webPage.evaluate(`
    chartData = ${chartJsonStr}
    if(chartData.options){
      chartData.options.animation=null
    } else {
      chartData.options = {
        animation: null
      }
    }

    function chartDraw (data) {
      var ctx = document.getElementById('myChart').getContext('2d')
      new Chart(ctx, data)
    }
    chartDraw(chartData)
  `)

    let inputElement = await webPage.$('#myChart')

    ctx.type = 'image/jpg'
    ctx.body = await inputElement.screenshot({}) //quality: 80
  },
  async mock (ctx) {
    const { mockJsonStr } = ctx.checkedData.data
    let mockObj = Mock.mock($.json.parse(mockJsonStr))
    ctx.ok(mockObj, '成功')
  },
  async checkPwd (ctx) {
    let ip =
      ctx.req.headers['x-forwarded-for'] ||
      ctx.req.connection.remoteAddress ||
      ctx.req.socket.remoteAddress ||
      ctx.req.connection.socket.remoteAddress
    const { pwdStr } = ctx.checkedData.data
    const r = await sqliteCheckPwdDB.all(
      `select 1 from pwd where pwd='${pwdStr}'`
    )
    if (r[0] || pwdStr.length < 6) {
      ctx.ok({ inputPwd: pwdStr, level: 1 }, '极度危险,立刻换掉')
      return
    }
    await sqliteCheckPwdDB.run(
      `insert into check_list  ('pwd','ip','c_time') values ('${pwdStr}','${ip}','${$.now().date2Str()}')`
    )
    if (!r[0] && pwdStr.length < 10) {
      ctx.ok({ inputPwd: pwdStr, level: 2 }, '不安全,考虑改变')
      return
    }
    ctx.ok({ inputPwd: pwdStr, level: 3 }, '较安全，只是相对')
  },
  async readQR (ctx) {
    const { qrStr } = ctx.checkedData.data
    console.log(qrStr)
    let buf
    try {
      if (qrStr.indexOf('data:image') === 0) {
        const base64 = qrStr.replace(/^data:image\/\w+;base64,/, '')
        buf = await jimp.read(Buffer.from(base64, 'base64'))
      } else {
        buf = await jimp.read(decodeURIComponent(qrStr))
      }
    } catch (e) {
      console.error(e)
      ctx.throwCode('410', '无法识别二维码', null)
      return
    }

    let r = await qrDecode(qr, buf.bitmap)
    if (r.errCode === -1) {
      ctx.throwCode('411', r.errMsg)
    } else {
      ctx.ok(r)
    }
  },
  async phone (ctx) {
    const { phoneStr } = ctx.checkedData.data
    const r = phoneFind(phoneStr)
    delete r.areacode
    ctx.ok(r)
  },
  async ipQuery (ctx) {
    const { ipStr } = ctx.checkedData.data
    try {
      const r = ipFind(ipStr)
      ctx.ok({ ip: r.ip, int: r.int, country: r.Country, area: r.Area })
    } catch (e) {
      ctx.throwCode(400, 'ip地址有误')
    }
  },
  async trans (ctx) {
    const { transStr, transType } = ctx.checkedData.data
    const o = { c2e: 'ZH_CN2EN', e2c: 'EN2ZH_CN' }

    try {
      const r = await getYouDao(transStr, o[transType])
      ctx.ok(r)
    } catch (e) {
      ctx.throwCode(400, '翻译失败')
    }
  },
  async latlng (ctx) {
    let { lat, lng, latlngType } = ctx.checkedData.data
    if (latlngType !== 'gd') {
      const gd = geo.bd2gd(lat, lng)
      ;[lat, lng] = [gd.lat, gd.lng]
    }
    let r = await geo.geo2Area(lat, lng)
    if (r) {
      ctx.ok({
        path: r.merger_name,
        phoneCode: r.code,
        zipCode: r.zip_code,
        lat: r.lat,
        lng: r.lng
      })
    } else {
      ctx.throwCode(404, '没找到对应中国地区', {})
    }
  },
  async covi (ctx) {
    const data = ctx.checkedData.data
    const nowDate = $.now()

    ctx.type = 'text/html'
    const tdTitle = ['序号', '城市', '确诊', '治愈', '死亡']
    const r = await getCovi()
    const objHtml = r[0]
    const title = '新冠19世界报告,总死亡: ' + r[1] || '--'
    let htmlResult
    if (!global.coviApi) {
      htmlResult = htmlOutModel.outHtml(title, [
        {
          title: title,
          dataTitleArr: tdTitle,
          dataArr: processCovi(objHtml.orderBy(['sure'], ['desc']))
        }
      ])
      global.coviApi = { t: +$.now(), c: htmlResult }
    } else {
      if (+$.now() - global.coviApi.t > 1800000) {
        htmlResult = htmlOutModel.outHtml(title, [
          {
            title: title,
            dataTitleArr: tdTitle,
            dataArr: processCovi(objHtml.orderBy(['sure'], ['desc']))
          }
        ])
        global.coviApi = { t: +$.now(), c: htmlResult }
      } else {
        //console.log('covi 缓存')
      }
    }
    ctx.body = global.coviApi.c
  },
  async coviAll (ctx) {
    const data = ctx.checkedData.data
    const nowDate = $.now()

    if (!global.coviAllApi) {
      global.coviAllApi = { t: +$.now(), c: await getCoviAll() }
    } else {
      if (+$.now() - global.coviAllApi.t > 1800000) {
        global.coviAllApi = { t: +$.now(), c: await getCoviAll() }
      } else {
        //console.log('covi 缓存')
      }
    }
    ctx.ok(global.coviAllApi.c)
  },
  async coviHtml (ctx) {
    const { displayType } = ctx.checkedData.data
    const nowDate = $.now()
    ctx.type = 'text/html'
    const tdTitle = [
      '序号',
      'level1',
      'Level2',
      'Level3',
      'Level4',
      '确认',
      '治愈',
      '死亡'
    ]

    if (!global.coviAllApi) {
      global.coviAllApi = { t: nowDate, c: await getCoviAll() }
    } else {
      if (nowDate - global.coviAllApi.t > 1800000) {
        global.coviAllApi = { t: nowDate, c: await getCoviAll() }
      } else {
        //console.log('covi 缓存')
      }
    }
    coviTree.length = 0
    walkTree(global.coviAllApi.c, 0, displayType)
    //console.log(coviTree)
    const title =
      '全球新冠 更新时间:' +
        new Date(global.coviAllApi.c.lastUpdated).date2Str() || ''

    ctx.body = htmlOutModel.outHtml(title, [
      {
        title: title,
        dataTitleArr: tdTitle,
        dataArr: processAllCovi(coviTree)
      }
    ])
  },
  async avatar (ctx) {
    let { str } = ctx.checkedData.data
    ctx.type = 'image/png'
    ctx.body = Buffer.from(genAvatar.toPng(md5(str), 64))
  }
}
// 扩展函数
const md5 = s => crypto.createHash('md5').update(s).digest('hex')

/**bing抓取 */
async function getBingCovi () {
  let url = `https://www.bing.com/covid`
  const r = await req(url, 'GET', true)
  let reg = /var ig=('|")(.+?)('|")/g
  reg.test(r)
  let ig = RegExp.$2
  reg = /token=('|")(.+?)('|")/g
  reg.test(r)
  //console.log(ig, RegExp.$2)
  return { ig: ig, token: RegExp.$2 } //BB1A1620DFC343338BF31BEEC7D3D041
}
async function getBingCoviJson (ig) {
  let url = `https://www.bing.com/covid/data?ig=` + ig.ig
  console.log('Basic ' + Buffer.from(ig.token).toString('base64'), url)

  //return
  const r = await req(url, 'GET', true, {
    authorization: 'Basic ' + Buffer.from(ig.token).toString('base64'),
    accept: '*/*',
    'accept-language': 'en-US,en;q=0.9,en;q=0.8', //'zh-CN,zh;q=0.9,en;q=0.8',
    'user-agent':
      'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
  })
  return r
}
async function getCoviAll () {
  const ig = await getBingCovi()
  return getBingCoviJson(ig)
}
let coviTree = []
function walkTree (obj, level = 0, type = '') {
  level++
  let objArea = obj.areas

  coviTree.push([
    ...Array(level - 1).fill(''),
    obj.displayName,
    ...Array(4 - level).fill(''),
    obj.totalConfirmed || 0,
    obj.totalRecovered || 0,
    obj.totalDeaths || 0
  ])
  if (objArea.length === 0) {
    //console.log(obj.displayName)

    return
  } else {
    if (type === '' && level > 1) return
    for (let i = 0; i < objArea.length; i++) {
      walkTree(objArea[i], level++, type)
      level--
    }
  }
}
function processAllCovi (o) {
  let n = 1
  let data = o.map(item => {
    return [n++, item[0], item[1], item[2], item[3], item[4], item[5], item[6]]
  })
  return data
}
/**bing 相关结束 */

async function getCovi () {
  let url = `https://cn.bing.com/covidmapapi/locations`
  let arr = []
  let dieSum = 0
  const r = await req(url, 'GET', true)
  for (let i = 0; i < r.length; i++) {
    let city = r[i].split('|')
    dieSum += +city[4]
    arr.push({ name: city[5], sure: +city[2], ok: +city[3], die: +city[4] })
  }
  return [arr, dieSum]
}
function processCovi (o) {
  let data = []
  let n = 1
  for (let k in o) {
    const item = o[k]
    if (o.hasOwnProperty(k)) {
      data.push([n++, item.name, item.sure, item.ok, item.die])
    }
  }
  return data
}
async function getYouDao (text, type) {
  if (text.trim() === '') return ''
  let url = `http://fanyi.youdao.com/translate?&doctype=json&type=${
    type || 'AUTO'
  }&i=${encodeURIComponent(text)}`
  const r = await req(url, 'GET', true)

  return r.translateResult[0][0].tgt
}
function processData (o) {
  let data = []
  let n = 1
  for (let k in o) {
    const item = o[k]
    if (o.hasOwnProperty(k)) {
      let year = +item.year
      let century =
        year === -999999
          ? '未知'
          : year < 0
          ? '前' + (Math.abs((year / 100) | 0) + 1) + '世纪'
          : ((year / 100) | 0) + 1 + '世纪'
      year = year === -999999 ? '未知' : year < 0 ? '公元前' + -year : year

      data.push([n++, century, year, item.desc, item.type])
    }
  }
  return data
}

async function req (
  url = 'http://www.baidu.com',
  method = 'GET',
  isJson = false,
  headers,
  proxy
) {
  let body = await request({
    method: method,
    json: isJson,
    url: url,
    responseType: 'json',
    timeout: 10000,
    proxy: proxy,
    headers: headers
  })
  return body
}

const qrDecode = async function (qr, bitmap) {
  return new Promise(function (resolve, reject) {
    qr.callback = function (err, value) {
      if (err) {
        reject({ errCode: -1, errMsg: '无法识别二维码.', result: '' })
      }
      resolve({ result: value.result })
    }
    qr.decode(bitmap)
  })
}

let dataXtest = {
  type: 'bar',
  data: {
    labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
    datasets: [
      {
        label: '条状图',
        data: [12, 19, 3, 5, 2, 13],
        backgroundColor: [
          'rgba(255, 99, 132, 0.2)',
          'rgba(54, 162, 235, 0.2)',
          'rgba(255, 206, 86, 0.2)',
          'rgba(75, 192, 192, 0.2)',
          'rgba(153, 102, 255, 0.2)',
          'rgba(255, 159, 64, 0.2)'
        ],
        borderColor: [
          'rgba(255, 99, 132, 1)',
          'rgba(54, 162, 235, 1)',
          'rgba(255, 206, 86, 1)',
          'rgba(75, 192, 192, 1)',
          'rgba(153, 102, 255, 1)',
          'rgba(255, 159, 64, 1)'
        ],
        borderWidth: 1
      }
    ]
  }
}
let mockXtest = {
  name: `@genName`,
  str: `@genData('abcdefghijklmnopqrstuvwxyz',10)`,
  datetime: `@genDatetime('2016-1-1','2016-2-2')`,
  card: `@genCard`,
  url: `@genUrl(5)`,
  phoneNum: `@genPhone`,
  color: `@genColor`,
  colorRGBA: `@genColor('rgba')`,
  ip: `@genIp`,
  word: '@genWord(10)',
  word0: '@genWord',
  sentence: `@genText(20)`,
  sentence20: `@genText(20)`,
  sentence10: `@genText(10)`,
  sentence0: `@genText`,
  sentence1: `@genBeautyText`,
  constellation: `@genConstellation`
  /*bool: `@genBool`,
      genEnum1: `@genEnum(['5',6,7])`,
      genEnum0: `@genEnum`,
      genEnum2: `@genEnum(['5x','6x','7x'])`,
      status: `@genEnum([[],null,''])`,
      skuCode: null,
      arrList: `@genList(10)`,
      arrList2: `@genList(10,2)`*/
}
//console.log(JSON.stringify(mockXtest))
